#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>
#include <cstdlib>
#include <ctime>

struct Family {
    std::string _name;
    size_t _money;
    int _times;
    std::string _transaction;

    Family(const std::string& name, size_t money, int times = 2)
        : _name(name), _money(money), _times(times) {}
};

pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER;
int money = 10;

void* deposit(void* args) {
    Family* person = static_cast<Family*>(args);
    pthread_mutex_lock(&pmutex);
    money += person->_money;
    std::cout << person->_transaction << ": " << person->_name << " deposit "
              << person->_money << " yuans, the account's money is: " << money << std::endl;
    pthread_mutex_unlock(&pmutex);
    delete person; // 删除动态分配的内存
    return nullptr;
}

void* withdraw(void* args) {
    Family* person = static_cast<Family*>(args);
    pthread_mutex_lock(&pmutex);
    money -= person->_money;
    std::cout << person->_transaction << ": " << person->_name << " withdraw "
              << person->_money << " yuans, the account's money is: " << money << std::endl;
    pthread_mutex_unlock(&pmutex);
    delete person; // 删除动态分配的内存
    return nullptr;
}

int main() {
    srand(time(0));

    std::vector<Family*> family; // 使用指针来管理Family结构体
    family.push_back(new Family("father", 10));
    family.push_back(new Family("mother", 20));
    family.push_back(new Family("granma", 30));
    family.push_back(new Family("granpa", 40));
    family.push_back(new Family("uncle", 50));
    family.push_back(new Family("mary", 50));
    family.push_back(new Family("sally", 100));

    std::vector<pthread_t*> threads;
    size_t times = 1;

    while (!family.empty()) {
        size_t index = rand() % family.size();
        if (family[index]->_times == 0) {
            // 删除动态分配的内存
            delete family[index]; 
            family.erase(family.begin() + index);
            continue;
        }

        family[index]->_times--;

        Family* personCopy = new Family(family[index]->_name, family[index]->_money, family[index]->_times);
        personCopy->_transaction = "transaction-" + std::to_string(times);

        pthread_t* t = new pthread_t; 
        threads.push_back(t);

        if (personCopy->_name == "mary" || personCopy->_name == "sally") 
            pthread_create(t, nullptr, withdraw, personCopy);            
        else 
            pthread_create(t, nullptr, deposit, personCopy);           
        
        times++;
    }

    for (auto& t : threads) {
        pthread_join(*t, nullptr);
        delete t;
    }

    std::cout << "finally, the account's money is: " << money << std::endl;

    return 0;
}